package campusguide;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GuideUI extends Application {

    private final int IMAGE_FIT_HEIGHT = 500;

    Image image;

    // Index Port By Circle
    private Map<Circle, Port> portOfCircles;

    CampusMap instance;
    Group mapAndCircles;

    // Convenience Method
    private HBox getTextInputRow(String what, String defaultText) {
        TextField textInput = new TextField(defaultText);
        HBox inputRow = new HBox();
        inputRow.getChildren().addAll(new Label(what + ": "), textInput);
        inputRow.setAlignment(Pos.CENTER_LEFT);
        inputRow.setSpacing(5);
        return inputRow;
    }

    Stage infoStage;
    Label portName;
    Label portIntro;

    // Convenience Method
    private Circle getCircleOfPort(Port p) {
        Circle circle = new Circle();
        circle.setFill(Color.RED);
        circle.setCenterX(p.getPosX());
        circle.setCenterY(p.getPosY());
        circle.setRadius(5);
        circle.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
            if (e.getClickCount() == 2) {
                Alert a = new Alert(Alert.AlertType.WARNING);
                a.setHeaderText("Double Click");
                a.showAndWait();
            } else {
                Port thePort = portOfCircles.get(circle);
                portName.setText(thePort.getName());
                portIntro.setText(thePort.getIntro());
                infoStage.show();
            }
        });
        return circle;
    }

    private Stage setPortAddingStage() {
        Stage portAddingStage = new Stage();

        // Set Image
        ImageView campusImage = new ImageView(image);
        campusImage.setPreserveRatio(true);
        campusImage.setFitHeight(IMAGE_FIT_HEIGHT);

        // Set Position Input Row
        Label positionXLabel = new Label("0");
        Label positionYLabel = new Label("0");
        HBox positionInputRow = new HBox();
        positionInputRow.getChildren().addAll(
                new Label("Position "),
                new Label("X: "),
                positionXLabel,
                new Label("Y: "),
                positionYLabel
        );
        positionInputRow.setSpacing(5);
        positionInputRow.setAlignment(Pos.CENTER_LEFT);

        // Set Position Get Event Handler
        campusImage.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
            positionXLabel.setText(String.valueOf(e.getX()));
            positionYLabel.setText(String.valueOf(e.getY()));
        });

        // Set Name Input
        HBox nameInputRow = getTextInputRow("Name", "Unnamed Port");

        // Set Intro Input Row
        HBox introInputRow = getTextInputRow("Intro", "");
        HBox attachmentInputRow = getTextInputRow("Attachment", "");

        Button addButton = new Button("Add");

        addButton.setOnMouseClicked(e -> {
            String name = ((TextField) nameInputRow.getChildren().get(1)).getText();
            String intro = ((TextField) introInputRow.getChildren().get(1)).getText();
            String attachment = ((TextField) attachmentInputRow.getChildren().get(1)).getText();
            Port newPort = new Port(
                    instance.getAvailablePortID(),
                    Double.parseDouble(positionXLabel.getText()),
                    Double.parseDouble(positionYLabel.getText()),
                    1,
                    name, intro, attachment);
            instance.addPort(newPort);
            // Make New Circle
            Circle newCircle = getCircleOfPort(newPort);
            // Put The Circle On Map
            mapAndCircles.getChildren().add(newCircle);
            // Record Association
            portOfCircles.put(newCircle, newPort);

            portAddingStage.close();
        });

        VBox elements = new VBox();
        elements.getChildren().addAll(
                positionInputRow,
                nameInputRow,
                introInputRow,
                attachmentInputRow,
                campusImage,
                addButton
        );
        elements.setSpacing(5);
        elements.setPadding(new Insets(10, 10, 10, 10));

        portAddingStage.setScene(new Scene(elements));

        return portAddingStage;
    }

    @Override
    public void start(Stage stage) throws Exception {

        instance = new CampusMapJSON();

        infoStage = new Stage();
        portName = new Label();
        portIntro = new Label();
        VBox infoStageElements = new VBox();
        infoStageElements.getChildren().addAll(portName, portIntro);
        infoStageElements.setAlignment(Pos.CENTER);
        infoStageElements.setPadding(new Insets(20, 20, 20, 20));
        infoStageElements.setSpacing(5);
        infoStage.setScene(new Scene(infoStageElements));

        // Campus Map Image
        image = new Image("./MUC_MAP.png");
        ImageView campusMapImage = new ImageView(image);
        campusMapImage.setPreserveRatio(true);
        campusMapImage.setFitHeight(IMAGE_FIT_HEIGHT);

        mapAndCircles = new Group();
        mapAndCircles.getChildren().add(campusMapImage);

        portOfCircles = new HashMap<>();
        List<Port> ports = instance.getAllMainPorts();

        for (Port p : ports) {
            Circle newCircle = getCircleOfPort(p);
            portOfCircles.put(newCircle, p);
            mapAndCircles.getChildren().add(newCircle);
        }

        Stage portAddingStage = setPortAddingStage();

        Button addButton = new Button("Add a port...");

        addButton.setOnMouseClicked(e -> {
            portAddingStage.show();
        });

        VBox mainStageElements = new VBox();
        mainStageElements.getChildren().addAll(mapAndCircles, addButton);
        mainStageElements.setSpacing(5);
        mainStageElements.setPadding(new Insets(10, 10, 10, 10));
        stage.setScene(new Scene(mainStageElements));
        stage.show();
    }
}
